//
//  SWImageCropper.swift
//  YiyaPuzzleDemo
//
//  Created by linhan on 16/10/13.
//  Copyright © 2016年 test. All rights reserved.
//

import Foundation
import UIKit

@objc protocol SWImageCropperDelegate:NSObjectProtocol
{
    @objc optional func imageCropperDidEndDragging(_ cropper:SWImageCropper)
    @objc optional func imageCropperWillBeginDragging(_ cropper:SWImageCropper)
    @objc optional func imageCropperDidEndZooming(_ cropper:SWImageCropper)
    
}

class SWImageCropper: UIView,UIScrollViewDelegate,SWIMainCanvas
{
    //裁剪原图
    weak var image:UIImage? {
        didSet{
            updateImage()
        }
    }
    
    var pluginCanvas:UIView?
    
    var size:CGSize{
        return frame.size
    }
    
    //裁剪框跟周边的距离
    var contentInsets:UIEdgeInsets = UIEdgeInsetsZero{
        didSet{
            updateCropView()
            if let _ = image{
                updateImage()
            }
        }
    }
    
    //裁剪宽高比
    var aspectRatio:CGFloat = 1{
        didSet{
            
        }
    }
    
    //最大放大比例
    var maximumZoomScale: CGFloat = 1.2{
        didSet{
            _scrollView.maximumZoomScale = maximumZoomScale
        }
    }
    
    weak var delegate:SWImageCropperDelegate?
    
    private var _scrollView:UIScrollView = UIScrollView()
    
    private var _imageView:UIImageView = UIImageView()
    private var _maskView:UIImageView = UIImageView()
    
    private var _canvasView:UIView = UIView()
    
    
    
    //辅助线
    private var _auxiliaryLineView:UIView = UIView()
    
    init()
    {
        super.init(frame: CGRectZero)
        setup()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override var frame: CGRect{
        get{
            return super.frame
        }
        set{
            let sizeChange = !super.frame.size.equalTo(newValue.size)
            super.frame = newValue
            if sizeChange
            {
                sizeChanged()
            }
        }
    }
    
    //裁剪区域
    var cropRectPercent:CGRect{
        let xPercent:CGFloat = _scrollView.contentOffset.x / _canvasView.width
        let yPercent:CGFloat = _scrollView.contentOffset.y / _canvasView.height
        let widthPercent:CGFloat = _scrollView.width / _canvasView.width
        let heightPercent:CGFloat = _scrollView.height / _canvasView.height
        return CGRectMake(xPercent, yPercent, widthPercent, heightPercent)
    }
    
    var cropRect:CGRect{
        let Percent = cropRectPercent
        let Size = image?.size ?? CGSizeZero
        let cropRect:CGRect = CGRectMake(Size.width * Percent.x, Size.height * Percent.y, Size.width * Percent.width, Size.height * Percent.height)
        return cropRect
    }
    
    private func setup()
    {
        clipsToBounds = true
        
        _scrollView.backgroundColor = UIColor.white
        _scrollView.delegate = self
        _scrollView.minimumZoomScale = 1
        _scrollView.maximumZoomScale = maximumZoomScale
        _scrollView.clipsToBounds = false
        _scrollView.showsHorizontalScrollIndicator = false
        _scrollView.showsVerticalScrollIndicator = false
        addSubview(_scrollView)
        
        _canvasView.addSubview(_imageView)
        _scrollView.addSubview(_canvasView)
        
        _maskView.isUserInteractionEnabled = false
        addSubview(_maskView)
        
        _auxiliaryLineView.isUserInteractionEnabled = false
        addSubview(_auxiliaryLineView)
    }
    
    private func sizeChanged()
    {
        updateCropView()
        
        if let _ = image{
            updateImage()
        }
    }
    
    private func updateCropView()
    {
        let containerAspectRatio:CGFloat = bounds.width / bounds.height
        let containerMinEdge:CGFloat = min(bounds.width, bounds.height)
        var rect = CGRectZero
        //var cropX:CGFloat = 0
        //var cropY:CGFloat = 0
        var cropWidth:CGFloat = 0
        var cropHeight:CGFloat = 0
        
        if aspectRatio == 1
        {
            if containerAspectRatio > 1
            {
                cropHeight = containerMinEdge - contentInsets.top - contentInsets.bottom
                cropWidth = cropHeight
            }
            else
            {
                cropWidth = containerMinEdge - contentInsets.left - contentInsets.right
                cropHeight = cropWidth
            }
            rect = CGRectMake((bounds.width - cropWidth) * 0.5, (bounds.height - cropHeight) * 0.5, cropWidth, cropHeight)
        }
        
        _scrollView.frame = rect
        drawMaskShape(rect)
        drawAuxiliaryLine()
    }
    
    private func updateImage()
    {
        guard let originImage = self.image else{
            return
        }
        
        var image:UIImage = originImage
        var imageWidth:CGFloat = image.size.width
        var imageHeight:CGFloat = image.size.height
        
        //先将巨大的原图缩小(但是控制在容器的2倍大，可以放大到2倍不模糊)，以提供流畅度
        var scale:CGFloat = ViewUtil.getAdaptiveScale(imageWidth, targetH: imageHeight, containerW: _scrollView.width * 2, containerH: _scrollView.height * 2, inscribed: false)
        if scale < 1
        {
            let size = CGSizeMake(imageWidth * scale, imageHeight * scale).divide(image.scale)
            image = Toucan.Resize.resizeImage(image, size: size, fitMode:.scale)
        }
        
        imageWidth = image.size.width
        imageHeight = image.size.height
        _imageView.image = image
        
        scale = ViewUtil.getAdaptiveScale(imageWidth, targetH: imageHeight, containerW: _scrollView.width, containerH: _scrollView.height, inscribed: false)
        imageWidth = imageWidth * scale
        imageHeight = imageHeight * scale
        _imageView.frame = CGRectMake(0, 0, imageWidth, imageHeight)
        
        _canvasView.frame = _imageView.frame
        
        _scrollView.setZoomScale(1, animated: true)
        _scrollView.contentSize = _imageView.frame.size
        _scrollView.contentOffset = CGPointMake((imageWidth - _scrollView.width) * 0.5, (imageHeight - _scrollView.height) * 0.5)
    }
    
    //绘制中间镂空的遮罩
    private func drawMaskShape(_ cropRect:CGRect)
    {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0);
        if let context:CGContext = UIGraphicsGetCurrentContext()
        {
            //半透明遮罩
            UIColor(white:0, alpha:0.6).setFill()
            UIRectFill(bounds)
            context.clear(cropRect);
            
            _maskView.image = UIGraphicsGetImageFromCurrentImageContext()
            _maskView.frame = bounds
            
            UIGraphicsEndImageContext()
        }
    }
    
    //绘制辅助线
    private func drawAuxiliaryLine()
    {
        _auxiliaryLineView.removeAllSubview()
        
        let ContainerWidth:CGFloat = _scrollView.width
        let ContainerHeight:CGFloat = _scrollView.height
        let LineWidth:CGFloat =  ContainerWidth - 1
        let LineHeight:CGFloat =  ContainerHeight - 1
        
        
        let color:UIColor = UIColor(hex:0xd6dfeb)
        let hLine1:UIView = UIView(frame: CGRectMake(0.5, ContainerHeight / 3, LineWidth, 0.5))
        hLine1.backgroundColor = color
        let hLine2:UIView = UIView(frame: CGRectMake(0.5, ContainerHeight * 2 / 3, LineWidth, 0.5))
        hLine2.backgroundColor = color
        
        let vLine1:UIView = UIView(frame: CGRectMake(ContainerWidth / 3, 0.5, 0.5, LineHeight))
        vLine1.backgroundColor = color
        let vLine2:UIView = UIView(frame: CGRectMake(ContainerWidth * 2 / 3, 0.5, 0.5, LineHeight))
        vLine2.backgroundColor = color
        
        _auxiliaryLineView.addSubview(hLine1)
        _auxiliaryLineView.addSubview(hLine2)
        _auxiliaryLineView.addSubview(vLine1)
        _auxiliaryLineView.addSubview(vLine2)
        _auxiliaryLineView.frame = _scrollView.frame
        //_auxiliaryLineView.hidden = true
        
        /**
        let borderView:UIView = UIView()
        borderView.frame = _scrollView.frame
        borderView.layer.borderColor = color.CGColor
        borderView.layer.borderWidth = 0.5
        borderView.userInteractionEnabled = false
        view.addSubview(borderView)
         **/
        
    }
    
    func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat)
    {
        delegate?.imageCropperDidEndZooming?(self)
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
    {
        delegate?.imageCropperDidEndDragging?(self)
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView)
    {
        delegate?.imageCropperWillBeginDragging?(self)
    }
    
    func viewForZooming(in scrollView: UIScrollView) -> UIView?
    {
        return _canvasView
    }
    
}
